﻿//Created by Action Script Viewer - http://www.buraks.com/asv
package de.polygonal.ds {
    import de.polygonal.ds.sort.*;
    import de.polygonal.ds.sort.compare.*;

    public class SLinkedList implements Collection {

        public static const INSERTION_SORT:int = (1 << 1);
        public static const MERGE_SORT:int = (1 << 2);
        public static const NUMERIC:int = (1 << 3);
        public static const DESCENDING:int = (1 << 4);

        private var _count:int;
        public var head:SListNode;
        public var tail:SListNode;

        public function SLinkedList(... _args){
            this.head = (this.tail = null);
            this._count = 0;
            if (_args.length > 0){
                this.append.apply(this, _args);
            };
        }
        public function append(... _args):SListNode{
            var _local4:SListNode;
            var _local5:int;
            var _local2:int = _args.length;
            var _local3:SListNode = new SListNode(_args[0]);
            if (this.head){
                this.tail.next = _local3;
                this.tail = _local3;
            } else {
                this.head = (this.tail = _local3);
            };
            if (_local2 > 1){
                _local4 = _local3;
                _local5 = 1;
                while (_local5 < _local2) {
                    _local3 = new SListNode(_args[_local5]);
                    this.tail.next = _local3;
                    this.tail = _local3;
                    _local5++;
                };
                this._count = (this._count + _local2);
                return (_local4);
            };
            this._count++;
            return (_local3);
        }
        public function prepend(... _args):SListNode{
            var _local4:SListNode;
            var _local5:int;
            var _local2:int = _args.length;
            var _local3:SListNode = new SListNode(_args[int((_local2 - 1))]);
            if (this.head){
                _local3.next = this.head;
                this.head = _local3;
            } else {
                this.head = (this.tail = _local3);
            };
            if (_local2 > 1){
                _local4 = _local3;
                _local5 = (_local2 - 2);
                while (_local5 >= 0) {
                    _local3 = new SListNode(_args[_local5]);
                    _local3.next = this.head;
                    this.head = _local3;
                    _local5--;
                };
                this._count = (this._count + _local2);
                return (_local4);
            };
            this._count++;
            return (_local3);
        }
        public function insertAfter(_arg1:SListIterator, _arg2):SListNode{
            var _local3:SListNode;
            if (_arg1.list != this){
                return (null);
            };
            if (_arg1.node){
                _local3 = new SListNode(_arg2);
                _arg1.node.insertAfter(_local3);
                if (_arg1.node == this.tail){
                    this.tail = _arg1.node.next;
                };
                this._count++;
                return (_local3);
            };
            return (this.append(_arg2));
        }
        public function remove(_arg1:SListIterator):Boolean{
            if (((!((_arg1.list == this))) || (!(_arg1.node)))){
                return (false);
            };
            var _local2:SListNode = this.head;
            if (_arg1.node == this.head){
                _arg1.forth();
                this.removeHead();
                return (true);
            };
            while (_local2.next != _arg1.node) {
                _local2 = _local2.next;
            };
            _arg1.forth();
            if (_local2.next == this.tail){
                this.tail = _local2;
            };
            _local2.next = _arg1.node;
            this._count--;
            return (true);
        }
        public function removeHead(){
            var _local1:*;
            var _local2:SListNode;
            if (this.head){
                _local1 = this.head.data;
                if (this.head == this.tail){
                    this.head = (this.tail = null);
                } else {
                    _local2 = this.head;
                    this.head = this.head.next;
                    _local2.next = null;
                    if (this.head == null){
                        this.tail = null;
                    };
                };
                this._count--;
                return (_local1);
            };
            return (null);
        }
        public function removeTail(){
            var _local1:*;
            var _local2:SListNode;
            if (this.tail){
                _local1 = this.tail.data;
                if (this.head == this.tail){
                    this.head = (this.tail = null);
                } else {
                    _local2 = this.head;
                    while (_local2.next != this.tail) {
                        _local2 = _local2.next;
                    };
                    this.tail = _local2;
                    _local2.next = null;
                };
                this._count--;
                return (_local1);
            };
            return (null);
        }
        public function merge(... _args):void{
            var _local2:SLinkedList;
            if (_args.length == 0){
                return;
            };
            _local2 = _args[0];
            if (_local2.head){
                if (this.head){
                    this.tail.next = _local2.head;
                    this.tail = _local2.tail;
                } else {
                    this.head = _local2.head;
                    this.tail = _local2.tail;
                };
                this._count = (this._count + _local2.size);
            };
            var _local3:int = _args.length;
            var _local4 = 1;
            while (_local4 < _local3) {
                _local2 = _args[_local4];
                if (_local2.head){
                    this.tail.next = _local2.head;
                    this.tail = _local2.tail;
                    this._count = (this._count + _local2.size);
                };
                _local4++;
            };
        }
        public function concat(... _args):SLinkedList{
            var _local3:SLinkedList;
            var _local4:SListNode;
            var _local2:SLinkedList = new SLinkedList();
            _local4 = this.head;
            while (_local4) {
                _local2.append(_local4.data);
                _local4 = _local4.next;
            };
            var _local5:int = _args.length;
            var _local6:int;
            while (_local6 < _local5) {
                _local3 = _args[_local6];
                _local4 = _local3.head;
                while (_local4) {
                    _local2.append(_local4.data);
                    _local4 = _local4.next;
                };
                _local6++;
            };
            return (_local2);
        }
        public function sort(... _args):void{
            var _local2:int;
            var _local3:Function;
            var _local4:*;
            if (this._count <= 1){
                return;
            };
            if (_args.length > 0){
                _local2 = 0;
                _local3 = null;
                _local4 = _args[0];
                if ((_local4 is Function)){
                    _local3 = _local4;
                    if (_args.length > 1){
                        _local4 = _args[1];
                        if ((_local4 is int)){
                            _local2 = _local4;
                        };
                    };
                } else {
                    if ((_local4 is int)){
                        _local2 = _local4;
                    };
                };
                if (Boolean(_local3)){
                    if ((_local2 & 2)){
                        this.head = sLinkedInsertionSortCmp(this.head, _local3, (_local2 == 18));
                    } else {
                        this.head = sLinkedMergeSortCmp(this.head, _local3, (_local2 == 16));
                    };
                } else {
                    if ((_local2 & 2)){
                        if ((_local2 & 4)){
                            if (_local2 == 22){
                                this.head = sLinkedInsertionSortCmp(this.head, compareStringCaseSensitiveDesc);
                            } else {
                                if (_local2 == 14){
                                    this.head = sLinkedInsertionSortCmp(this.head, compareStringCaseInSensitive);
                                } else {
                                    if (_local2 == 30){
                                        this.head = sLinkedInsertionSortCmp(this.head, compareStringCaseInSensitiveDesc);
                                    } else {
                                        this.head = sLinkedInsertionSortCmp(this.head, compareStringCaseSensitive);
                                    };
                                };
                            };
                        } else {
                            this.head = sLinkedInsertionSort(this.head, (_local2 == 18));
                        };
                    } else {
                        if ((_local2 & 4)){
                            if (_local2 == 20){
                                this.head = sLinkedMergeSortCmp(this.head, compareStringCaseSensitiveDesc);
                            } else {
                                if (_local2 == 12){
                                    this.head = sLinkedMergeSortCmp(this.head, compareStringCaseInSensitive);
                                } else {
                                    if (_local2 == 28){
                                        this.head = sLinkedMergeSortCmp(this.head, compareStringCaseInSensitiveDesc);
                                    } else {
                                        this.head = sLinkedMergeSortCmp(this.head, compareStringCaseSensitive);
                                    };
                                };
                            };
                        } else {
                            if ((_local2 & 16)){
                                this.head = sLinkedMergeSort(this.head, true);
                            };
                        };
                    };
                };
            } else {
                this.head = sLinkedMergeSort(this.head);
            };
        }
        public function nodeOf(_arg1, _arg2:SListIterator=null):SListIterator{
            if (_arg2 != null){
                if (_arg2.list != null){
                    return (null);
                };
            };
            var _local3:SListNode = ((_arg2)==null) ? this.head : _arg2.node;
            while (_local3) {
                if (_local3.data === _arg1){
                    return (new SListIterator(this, _local3));
                };
                _local3 = _local3.next;
            };
            return (null);
        }
        public function splice(_arg1:SListIterator, _arg2:uint=4294967295, ... _args):SLinkedList{
            var _local4:SListNode;
            var _local5:SListNode;
            var _local6:SLinkedList;
            var _local7:int;
            var _local8:int;
            var _local9:SListNode;
            if (_arg1){
                if (_arg1.list != this){
                    return (null);
                };
            };
            if (_arg1.node){
                _local4 = _arg1.node;
                _local5 = this.head;
                while (_local5.next != _local4) {
                    _local5 = _local5.next;
                };
                _local6 = new SLinkedList();
                if (_arg2 == 4294967295){
                    if (_arg1.node == this.tail){
                        return (_local6);
                    };
                    while (_arg1.node) {
                        _local6.append(_arg1.node.data);
                        _arg1.remove();
                    };
                    _arg1.list = _local6;
                    _arg1.node = _local4;
                    return (_local6);
                };
                _local7 = 0;
                while (_local7 < _arg2) {
                    if (_arg1.node){
                        _local6.append(_arg1.node.data);
                        _arg1.remove();
                    } else {
                        break;
                    };
                    _local7++;
                };
                _local8 = _args.length;
                if (_local8 > 0){
                    if (this._count == 0){
                        _local7 = 0;
                        while (_local7 < _local8) {
                            this.append(_args[_local7]);
                            _local7++;
                        };
                    } else {
                        if (_local5 == null){
                            _local9 = this.prepend(_args[0]);
                            _local7 = 1;
                            while (_local7 < _local8) {
                                _local9.insertAfter(new SListNode(_args[_local7]));
                                if (_local9 == this.tail){
                                    this.tail = _local9.next;
                                };
                                _local9 = _local9.next;
                                this._count++;
                                _local7++;
                            };
                        } else {
                            _local9 = _local5;
                            _local7 = 0;
                            while (_local7 < _local8) {
                                _local9.insertAfter(new SListNode(_args[_local7]));
                                if (_local9 == this.tail){
                                    this.tail = _local9.next;
                                };
                                _local9 = _local9.next;
                                this._count++;
                                _local7++;
                            };
                        };
                    };
                    _arg1.node = _local9;
                } else {
                    _arg1.node = _local4;
                };
                _arg1.list = _local6;
                return (_local6);
            };
            return (null);
        }
        public function shiftUp():void{
            var _local1:SListNode = this.head;
            if (this.head.next == this.tail){
                this.head = this.tail;
                this.tail = _local1;
                this.tail.next = null;
                this.head.next = this.tail;
            } else {
                this.head = this.head.next;
                this.tail.next = _local1;
                _local1.next = null;
                this.tail = _local1;
            };
        }
        public function popDown():void{
            var _local2:SListNode;
            var _local1:SListNode = this.tail;
            if (this.head.next == this.tail){
                this.tail = this.head;
                this.head = _local1;
                this.tail.next = null;
                this.head.next = this.tail;
            } else {
                _local2 = this.head;
                while (_local2.next != this.tail) {
                    _local2 = _local2.next;
                };
                this.tail = _local2;
                this.tail.next = null;
                _local1.next = this.head;
                this.head = _local1;
            };
        }
        public function reverse():void{
            if (this._count == 0){
                return;
            };
            var _local1:Array = new Array(this._count);
            var _local2:int;
            var _local3:SListNode = this.head;
            while (_local3) {
                var _temp1 = _local2;
                _local2 = (_local2 + 1);
                var _local4 = _temp1;
                _local1[_local4] = _local3;
                _local3 = _local3.next;
            };
            _local1.reverse();
            _local3 = (this.head = _local1[0]);
            _local2 = 1;
            while (_local2 < this._count) {
                _local3 = (_local3.next = _local1[_local2]);
                _local2++;
            };
            _local3.next = null;
            this.tail = _local3;
            _local1 = null;
        }
        public function join(_arg1):String{
            if (this._count == 0){
                return ("");
            };
            var _local2 = "";
            var _local3:SListNode = this.head;
            while (_local3.next) {
                _local2 = (_local2 + (_local3.data + _arg1));
                _local3 = _local3.next;
            };
            _local2 = (_local2 + _local3.data);
            return (_local2);
        }
        public function contains(_arg1):Boolean{
            var _local2:SListNode = this.head;
            while (_local2) {
                if (_local2.data == _arg1){
                    return (true);
                };
                _local2 = _local2.next;
            };
            return (false);
        }
        public function clear():void{
            var _local2:SListNode;
            var _local1:SListNode = this.head;
            this.head = null;
            while (_local1) {
                _local2 = _local1.next;
                _local1.next = null;
                _local1 = _local2;
            };
            this._count = 0;
        }
        public function getIterator():Iterator{
            return (new SListIterator(this, this.head));
        }
        public function getListIterator():SListIterator{
            return (new SListIterator(this, this.head));
        }
        public function get size():int{
            return (this._count);
        }
        public function isEmpty():Boolean{
            return ((this._count == 0));
        }
        public function toArray():Array{
            var _local1:Array = [];
            var _local2:SListNode = this.head;
            while (_local2) {
                _local1.push(_local2.data);
                _local2 = _local2.next;
            };
            return (_local1);
        }
        public function toString():String{
            return ((("[SlinkedList, size=" + this.size) + "]"));
        }
        public function dump():String{
            if (!this.head){
                return ("SLinkedList: (empty)");
            };
            var _local1 = (((("SLinkedList: has " + this._count) + " node") + ((this._count == 1)) ? "" : "s") + "\n|< Head\n");
            var _local2:SListIterator = this.getListIterator();
            while (_local2.valid()) {
                _local1 = (_local1 + (("\t" + _local2.data) + "\n"));
                _local2.forth();
            };
            _local1 = (_local1 + "Tail >|");
            return (_local1);
        }

    }
}//package de.polygonal.ds 
